﻿using System;
using System.Diagnostics;
using System.IO;
using Reflector;
using Reflector.CodeModel;

namespace Neovolve.Extensibility.Reflector.DeadLinkRemover
{
    /// <summary>
    /// The <see cref="RemoverPackage"/>
    /// class removes assemblies that cannot be resolved by Reflector.
    /// </summary>
    public class RemoverPackage : IPackage
    {
        /// <summary>
        /// Loads the specified service provider.
        /// </summary>
        /// <param name="serviceProvider">The service provider.</param>
        public void Load(IServiceProvider serviceProvider)
        {
            LaunchDebugger();

            // Get AssemblyManager reference for reordering
            AssemblyManager = (IAssemblyManager)serviceProvider.GetService(typeof(IAssemblyManager));

            RemoveDeadAssemblies();

            AssemblyManager.AssemblyLoaded += AssemblyManager_AssemblyLoaded;
        }

        /// <summary>
        /// Launches the debugger.
        /// </summary>
        [Conditional("DEBUG")]
        private static void LaunchDebugger()
        {
            if (Debugger.IsAttached == false)
            {
                Debugger.Break();
            }
        }

        /// <summary>
        /// Unloads this instance.
        /// </summary>
        public void Unload()
        {
            AssemblyManager.AssemblyLoaded -= AssemblyManager_AssemblyLoaded;
        }

        /// <summary>
        /// Handles the AssemblyLoaded event of the AssemblyManager control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void AssemblyManager_AssemblyLoaded(object sender, EventArgs e)
        {
            RemoveDeadAssemblies();
        }

        /// <summary>
        /// Removes the dead assemblies.
        /// </summary>
        private void RemoveDeadAssemblies()
        {
            // Loop through the assemblies to find the first index that is out of order
            for (Int32 index = AssemblyManager.Assemblies.Count - 1; index >= 0; index--)
            {
                // Get the sorted assembly and the loaded assembly for the index
                IAssembly loadedAssembly = AssemblyManager.Assemblies[index];

                if (File.Exists(loadedAssembly.Location) == false)
                {
                    AssemblyManager.Assemblies.Remove(loadedAssembly);
                }
            }
        }

        /// <summary>
        /// Gets or sets the assembly manager.
        /// </summary>
        /// <value>The assembly manager.</value>
        private IAssemblyManager AssemblyManager
        {
            get;
            set;
        }
    }
}